package com.qst.service.impl;

import com.qst.pojo.entity.Order;
import com.qst.pojo.entity.Station;
import com.qst.pojo.entity.SystemSettings;
import com.qst.pojo.entity.User;
import com.qst.repository.StationRepository;
import com.qst.repository.SystemSettingsRepository;
import com.qst.repository.UserRepository;
import com.qst.service.EmailService;
import com.qst.service.NotificationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 通知服务实现类
 */
@Service
public class NotificationServiceImpl implements NotificationService {

    private static final Logger logger = LoggerFactory.getLogger(NotificationServiceImpl.class);
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private EmailService emailService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private StationRepository stationRepository;

    @Autowired
    private SystemSettingsRepository settingsRepository;

    /**
     * 发送新订单通知给站长
     */
    @Async
    @Override
    public void sendNewOrderNotification(Order order) {
        try {
            // 检查是否启用新订单通知
            if (!isNotificationEnabled("notification.newOrderNotification")) {
                return;
            }

            // 获取站点信息
            Optional<Station> stationOpt = stationRepository.findById(order.getStationId());
            if (!stationOpt.isPresent()) {
                logger.warn("站点不存在，无法发送新订单通知");
                return;
            }

            Station station = stationOpt.get();
            
            // 获取站长信息
            if (station.getManagerId() == null) {
                logger.warn("站点 {} 未分配站长，无法发送新订单通知", station.getName());
                return;
            }

            Optional<User> managerOpt = userRepository.findById(station.getManagerId());
            if (!managerOpt.isPresent() || managerOpt.get().getEmail() == null || managerOpt.get().getEmail().isEmpty()) {
                logger.warn("站长邮箱为空，无法发送新订单通知");
                return;
            }

            User manager = managerOpt.get();
            
            // 获取客户信息
            Optional<User> customerOpt = userRepository.findById(order.getCustomerId());
            String customerName = customerOpt.map(User::getRealName).orElse("未知客户");
            String customerPhone = customerOpt.map(User::getPhone).orElse("未提供");

            // 构建邮件内容
            String subject = "【新订单通知】您有一个新的回收订单";
            String content = String.format(
                "尊敬的 %s 站长：\n\n" +
                "您好！您的站点有一个新的回收订单，请及时处理。\n\n" +
                "订单详情：\n" +
                "----------------------------------------\n" +
                "订单编号：%s\n" +
                "客户姓名：%s\n" +
                "客户电话：%s\n" +
                "上门地址：%s\n" +
                "预约时间：%s\n" +
                "订单金额：¥%.2f\n" +
                "订单重量：%.2f kg\n" +
                "订单状态：待确认\n" +
                "下单时间：%s\n" +
                "----------------------------------------\n\n" +
                "备注：%s\n\n" +
                "请登录管理后台查看详细信息并及时处理。\n\n" +
                "资源回收管理平台\n" +
                "%s",
                manager.getRealName(),
                order.getOrderNo(),
                customerName,
                customerPhone,
                order.getPickupAddress(),
                order.getPickupTime() != null ? order.getPickupTime().format(DATE_FORMATTER) : "未指定",
                order.getTotalAmount(),
                order.getTotalWeight(),
                order.getCreatedAt().format(DATE_FORMATTER),
                order.getNotes() != null ? order.getNotes() : "无",
                java.time.LocalDateTime.now().format(DATE_FORMATTER)
            );

            emailService.sendSimpleEmail(manager.getEmail(), subject, content);

        } catch (Exception e) {
            logger.error("发送新订单通知失败", e);
        }
    }

    /**
     * 发送订单创建确认邮件给客户
     */
    @Override
    @Async
    public void sendOrderConfirmationToCustomer(Order order) {
        try {
            // 获取客户信息
            Optional<User> customerOpt = userRepository.findById(order.getCustomerId());
            if (!customerOpt.isPresent()) {
                logger.warn("客户不存在，无法发送订单确认邮件");
                return;
            }

            User customer = customerOpt.get();
            
            // 检查客户邮箱
            if (customer.getEmail() == null || customer.getEmail().trim().isEmpty()) {
                logger.warn("客户邮箱为空，无法发送订单确认邮件: customerId={}", customer.getId());
                return;
            }

            // 获取站点信息
            String stationName = "未指定";
            if (order.getStationId() != null) {
                Optional<Station> stationOpt = stationRepository.findById(order.getStationId());
                if (stationOpt.isPresent()) {
                    stationName = stationOpt.get().getName();
                }
            }

            // 构建邮件内容
            String subject = "【订单确认】您的回收订单已提交成功 - " + order.getOrderNo();
            String content = String.format(
                "尊敬的 %s：\n\n" +
                "您好！感谢您使用资源回收服务，您的订单已成功提交。\n\n" +
                "订单详情：\n" +
                "----------------------------------------\n" +
                "订单编号：%s\n" +
                "订单状态：待确认\n" +
                "回收站点：%s\n" +
                "上门地址：%s\n" +
                "预约时间：%s\n" +
                "预估金额：¥%.2f\n" +
                "预估重量：%.2f kg\n" +
                "下单时间：%s\n" +
                "----------------------------------------\n\n" +
                "订单备注：%s\n\n" +
                "温馨提示：\n" +
                "• 回收站点将在24小时内确认您的订单\n" +
                "• 确认后工作人员会按预约时间上门回收\n" +
                "• 实际金额将根据现场称重后确定\n" +
                "• 您可以随时登录系统查看订单状态\n\n" +
                "如有任何问题，请联系客服或回收站点。\n\n" +
                "资源回收管理平台\n" +
                "%s",
                customer.getRealName() != null ? customer.getRealName() : customer.getUsername(),
                order.getOrderNo(),
                stationName,
                order.getPickupAddress(),
                order.getPickupTime() != null ? order.getPickupTime().format(DATE_FORMATTER) : "未指定，站点会与您联系",
                order.getTotalAmount(),
                order.getTotalWeight(),
                order.getCreatedAt().format(DATE_FORMATTER),
                order.getNotes() != null && !order.getNotes().trim().isEmpty() ? order.getNotes() : "无",
                java.time.LocalDateTime.now().format(DATE_FORMATTER)
            );

            emailService.sendSimpleEmail(customer.getEmail(), subject, content);

        } catch (Exception e) {
            logger.error("发送订单确认邮件失败: orderNo={}", order.getOrderNo(), e);
        }
    }

    /**
     * 发送订单状态更新通知给客户
     */
    @Async
    @Override
    public void sendOrderStatusUpdateNotification(Order order, String oldStatus, String newStatus) {
        try {
            // 检查是否启用订单状态更新通知
            if (!isNotificationEnabled("notification.orderStatusUpdate")) {
                return;
            }

            // 获取客户信息
            Optional<User> customerOpt = userRepository.findById(order.getCustomerId());
            if (!customerOpt.isPresent() || customerOpt.get().getEmail() == null || customerOpt.get().getEmail().isEmpty()) {
                logger.warn("客户邮箱为空，无法发送订单状态更新通知");
                return;
            }

            User customer = customerOpt.get();

            // 状态中文映射
            String oldStatusCn = getStatusChinese(oldStatus);
            String newStatusCn = getStatusChinese(newStatus);

            // 构建邮件内容
            String subject = "【订单状态更新】您的订单状态已变更";
            String content = String.format(
                "尊敬的 %s：\n\n" +
                "您好！您的回收订单状态已更新。\n\n" +
                "订单信息：\n" +
                "----------------------------------------\n" +
                "订单编号：%s\n" +
                "订单金额：¥%.2f\n" +
                "上门地址：%s\n" +
                "预约时间：%s\n" +
                "状态变更：%s → %s\n" +
                "更新时间：%s\n" +
                "----------------------------------------\n\n" +
                "%s\n\n" +
                "如有疑问，请登录系统查看详细信息或联系客服。\n\n" +
                "资源回收管理平台\n" +
                "%s",
                customer.getRealName(),
                order.getOrderNo(),
                order.getTotalAmount(),
                order.getPickupAddress(),
                order.getPickupTime() != null ? order.getPickupTime().format(DATE_FORMATTER) : "未指定",
                oldStatusCn,
                newStatusCn,
                java.time.LocalDateTime.now().format(DATE_FORMATTER),
                getStatusDescription(newStatus),
                java.time.LocalDateTime.now().format(DATE_FORMATTER)
            );

            emailService.sendSimpleEmail(customer.getEmail(), subject, content);

        } catch (Exception e) {
            logger.error("发送订单状态更新通知失败", e);
        }
    }

    /**
     * 发送系统维护通知给所有客户和站长
     */
    @Async
    @Override
    public void sendMaintenanceNotification(boolean isMaintenanceMode) {
        try {
            // 检查是否启用系统维护通知
            if (!isNotificationEnabled("notification.maintenanceNotification")) {
                return;
            }

            // 获取所有非管理员用户（客户和站长）
            List<User> users = userRepository.findAll();
            List<String> emails = users.stream()
                    .filter(user -> user.getRole() != User.UserRole.admin)
                    .filter(user -> user.getEmail() != null && !user.getEmail().isEmpty())
                    .map(User::getEmail)
                    .distinct()
                    .collect(Collectors.toList());

            if (emails.isEmpty()) {
                logger.warn("没有找到可发送维护通知的用户邮箱");
                return;
            }

            // 构建邮件内容
            String subject;
            String content;

            if (isMaintenanceMode) {
                subject = "【系统维护通知】系统将进入维护状态";
                content = String.format(
                    "尊敬的用户：\n\n" +
                    "您好！资源回收管理平台将进入系统维护状态。\n\n" +
                    "维护期间，普通用户将无法登录系统。\n" +
                    "维护开始时间：%s\n\n" +
                    "维护期间可能影响的功能：\n" +
                    "• 用户登录\n" +
                    "• 订单提交\n" +
                    "• 数据查询\n\n" +
                    "我们会尽快完成维护工作，请您耐心等待。\n" +
                    "感谢您的理解与支持！\n\n" +
                    "如有紧急问题，请联系客服热线。\n\n" +
                    "资源回收管理平台\n" +
                    "%s",
                    java.time.LocalDateTime.now().format(DATE_FORMATTER),
                    java.time.LocalDateTime.now().format(DATE_FORMATTER)
                );
            } else {
                subject = "【系统恢复通知】系统维护已完成";
                content = String.format(
                    "尊敬的用户：\n\n" +
                    "您好！资源回收管理平台系统维护已完成。\n\n" +
                    "恢复时间：%s\n\n" +
                    "现在您可以正常使用系统的所有功能：\n" +
                    "• 登录账户\n" +
                    "• 提交订单\n" +
                    "• 查询数据\n\n" +
                    "感谢您在维护期间的耐心等待！\n" +
                    "如在使用过程中遇到任何问题，请及时联系我们。\n\n" +
                    "资源回收管理平台\n" +
                    "%s",
                    java.time.LocalDateTime.now().format(DATE_FORMATTER),
                    java.time.LocalDateTime.now().format(DATE_FORMATTER)
                );
            }

            // 发送给所有用户
            for (String email : emails) {
                try {
                    emailService.sendSimpleEmail(email, subject, content);
                } catch (Exception e) {
                    logger.error("发送维护通知失败到: {}", email, e);
                }
            }

        } catch (Exception e) {
            logger.error("发送系统维护通知失败", e);
        }
    }

    /**
     * 发送用户注册成功通知
     */
    @Async
    @Override
    public void sendUserRegistrationNotification(User user) {
        try {
            // 检查是否启用用户注册通知
            if (!isNotificationEnabled("notification.userRegistrationNotification")) {
                return;
            }

            if (user.getEmail() == null || user.getEmail().isEmpty()) {
                logger.warn("用户邮箱为空，无法发送注册通知");
                return;
            }

            // 角色中文
            String roleCn = user.getRole() == User.UserRole.customer ? "客户" : "站点管理员";

            // 构建邮件内容
            String subject = "【注册成功】欢迎加入资源回收管理平台";
            String content = String.format(
                "尊敬的 %s：\n\n" +
                "恭喜您！您已成功注册资源回收管理平台账户。\n\n" +
                "账户信息：\n" +
                "----------------------------------------\n" +
                "用户名：%s\n" +
                "真实姓名：%s\n" +
                "账户角色：%s\n" +
                "联系电话：%s\n" +
                "邮箱地址：%s\n" +
                "注册时间：%s\n" +
                "----------------------------------------\n\n" +
                "%s\n\n" +
                "温馨提示：\n" +
                "• 请妥善保管您的账户密码\n" +
                "• 定期更新个人信息以便我们更好地为您服务\n" +
                "• 如有任何问题，请随时联系客服\n\n" +
                "感谢您选择我们的平台！\n\n" +
                "资源回收管理平台\n" +
                "%s",
                user.getRealName(),
                user.getUsername(),
                user.getRealName(),
                roleCn,
                user.getPhone(),
                user.getEmail(),
                user.getCreatedAt() != null ? user.getCreatedAt().format(DATE_FORMATTER) : java.time.LocalDateTime.now().format(DATE_FORMATTER),
                getRoleWelcomeMessage(user.getRole()),
                java.time.LocalDateTime.now().format(DATE_FORMATTER)
            );

            emailService.sendSimpleEmail(user.getEmail(), subject, content);

        } catch (Exception e) {
            logger.error("发送用户注册通知失败", e);
        }
    }

    /**
     * 检查通知是否启用
     */
    private boolean isNotificationEnabled(String key) {
        Optional<SystemSettings> setting = settingsRepository.findBySettingKey(key);
        return setting.map(s -> Boolean.parseBoolean(s.getSettingValue())).orElse(true);
    }

    /**
     * 获取订单状态中文名称
     */
    private String getStatusChinese(String status) {
        switch (status) {
            case "pending": return "待确认";
            case "confirmed": return "已确认";
            case "in_progress": return "进行中";
            case "completed": return "已完成";
            case "cancelled": return "已取消";
            default: return status;
        }
    }

    /**
     * 获取订单状态描述
     */
    private String getStatusDescription(String status) {
        switch (status) {
            case "pending":
                return "您的订单已提交，正在等待站点确认。";
            case "confirmed":
                return "您的订单已确认，回收人员将按预约时间上门服务。";
            case "in_progress":
                return "回收人员正在处理您的订单，请耐心等待。";
            case "completed":
                return "您的订单已完成，感谢您对环保事业的支持！";
            case "cancelled":
                return "您的订单已取消，如有疑问请联系客服。";
            default:
                return "订单状态已更新。";
        }
    }

    /**
     * 获取角色欢迎信息
     */
    private String getRoleWelcomeMessage(User.UserRole role) {
        if (role == User.UserRole.customer) {
            return "作为客户，您可以：\n" +
                   "• 在线提交回收订单\n" +
                   "• 查看订单状态和历史记录\n" +
                   "• 管理个人信息\n" +
                   "• 享受便捷的上门回收服务";
        } else if (role == User.UserRole.station_manager) {
            return "作为站点管理员，您可以：\n" +
                   "• 管理站点信息\n" +
                   "• 处理客户订单\n" +
                   "• 查看站点数据统计\n" +
                   "• 为环保事业贡献力量";
        }
        return "欢迎使用资源回收管理平台！";
    }

    /**
     * 发送低库存警告
     */
    @Async
    @Override
    public void sendLowStockAlert(Station station, int threshold) {
        try {
            // 获取站长信息
            if (station.getManagerId() == null) {
                logger.warn("站点 {} 未分配站长，无法发送低库存警告", station.getName());
                return;
            }

            Optional<User> managerOpt = userRepository.findById(station.getManagerId());
            if (!managerOpt.isPresent() || managerOpt.get().getEmail() == null || managerOpt.get().getEmail().isEmpty()) {
                logger.warn("站长邮箱为空，无法发送低库存警告");
                return;
            }

            User manager = managerOpt.get();

            // 构建邮件内容
            String subject = "【库存警告】站点库存低于安全阈值";
            String content = String.format(
                "尊敬的 %s 站长：\n\n" +
                "您好！您管理的站点库存已低于安全阈值，请及时补充库存。\n\n" +
                "站点信息：\n" +
                "----------------------------------------\n" +
                "站点名称：%s\n" +
                "当前库存：%.2f kg\n" +
                "安全阈值：%d kg\n" +
                "站点地址：%s\n" +
                "警告时间：%s\n" +
                "----------------------------------------\n\n" +
                "建议措施：\n" +
                "• 检查库存情况\n" +
                "• 联系上级调配资源\n" +
                "• 暂停接收新订单\n\n" +
                "请尽快处理，以免影响正常业务运营。\n\n" +
                "资源回收管理平台\n" +
                "%s",
                manager.getRealName(),
                station.getName(),
                station.getCurrentLoad(),
                threshold,
                station.getAddress(),
                java.time.LocalDateTime.now().format(DATE_FORMATTER),
                java.time.LocalDateTime.now().format(DATE_FORMATTER)
            );

            emailService.sendSimpleEmail(manager.getEmail(), subject, content);

        } catch (Exception e) {
            logger.error("发送低库存警告失败", e);
        }
    }

    /**
     * 发送满载库存警告
     */
    @Async
    @Override
    public void sendFullStockAlert(Station station, int threshold) {
        try {
            // 获取站长信息
            if (station.getManagerId() == null) {
                logger.warn("站点 {} 未分配站长，无法发送满载警告", station.getName());
                return;
            }

            Optional<User> managerOpt = userRepository.findById(station.getManagerId());
            if (!managerOpt.isPresent() || managerOpt.get().getEmail() == null || managerOpt.get().getEmail().isEmpty()) {
                logger.warn("站长邮箱为空，无法发送满载警告");
                return;
            }

            User manager = managerOpt.get();

            // 构建邮件内容
            String subject = "【库存警告】站点库存已达到满载状态";
            String content = String.format(
                "尊敬的 %s 站长：\n\n" +
                "您好！您管理的站点库存已达到满载状态，请及时处理。\n\n" +
                "站点信息：\n" +
                "----------------------------------------\n" +
                "站点名称：%s\n" +
                "当前库存：%d kg\n" +
                "满载阈值：%d kg\n" +
                "站点地址：%s\n" +
                "警告时间：%s\n" +
                "----------------------------------------\n\n" +
                "建议措施：\n" +
                "• 安排物流转运\n" +
                "• 联系上级处理库存\n" +
                "• 暂停接收新订单\n\n" +
                "请尽快安排转运，以免影响正常业务运营。\n\n" +
                "资源回收管理平台\n" +
                "%s",
                manager.getRealName(),
                station.getName(),
                station.getCurrentLoad(),
                threshold,
                station.getAddress(),
                java.time.LocalDateTime.now().format(DATE_FORMATTER),
                java.time.LocalDateTime.now().format(DATE_FORMATTER)
            );

            emailService.sendSimpleEmail(manager.getEmail(), subject, content);

        } catch (Exception e) {
            logger.error("发送满载警告失败", e);
        }
    }
}

